import type { DocMenuT } from '@/@types/type-doc-menu';

export interface DocMenuNodeT {
  id: string;
  label: string;
  depth: number;
  href?: string;
  parent: DocMenuNodeT | null;
  children: Array<DocMenuNodeT>;
}

export class DocMenuTree {
  root: DocMenuNodeT;
  constructor(data: Array<DocMenuT>, base: string = '/docs') {
    this.root = {
      id: '',
      label: '',
      depth: 0,
      href: base,
      parent: null,
      children: [],
    };

    this.buildTree(this.root, data);
  }

  /**
   * 迭代构造树
   * @param {DocMenuNodeT} parent 父节点
   * @param {Array<DocMenuT>} data 数据
   */
  buildTree(parent: DocMenuNodeT, data: Array<DocMenuT>) {
    for (let i = 0, len = data.length; i < len; i++) {
      const curDepth = parent.depth + 1;
      const info = data[i];
      const node: DocMenuNodeT = {
        id: info.id,
        label: info.label,
        depth: curDepth,
        parent,
        children: [],
      };

      parent.children.push(node);

      let path = parent.href || '';

      if (info.href) {
        path = info.href;
      } else if (info.id) {
        path += `/${info.id}`;
      }

      node.href = path;

      if (info.children && info.children.length) {
        this.buildTree(node, info.children);
      }
    }
  }

  /**
   * BFS 广度优先查找节点
   * @param {DocMenuNodeT} node 父节点
   * @param {string} val id值
   * @returns {(DocMenuNodeT|undefined)} 查找到节点则返回该节点，未找到返回undefined
   */
  getNode(node: DocMenuNodeT, val: string): DocMenuNodeT | undefined {
    if (node.href === val) {
      return node;
    }

    const children: Array<DocMenuNodeT> = node.children;
    for (let i = 0, len = children.length; i < len; i++) {
      const rlt = this.getNode(children[i], val);
      if (rlt) {
        return rlt;
      }
    }
  }

  /**
   * BFS 广度优先查找节点
   * @param {DocMenuNodeT} node 父节点
   * @param {string} val href值
   * @returns {(DocMenuNodeT|undefined)} 查找到节点则返回该节点，未找到返回undefined
   */
  getNodeByHref(node: DocMenuNodeT, val: string): DocMenuNodeT | undefined {
    if (node.href === val) {
      return node;
    }

    const children: Array<DocMenuNodeT> = node.children;
    for (let i = 0, len = children.length; i < len; i++) {
      const rlt = this.getNodeByHref(children[i], val);
      if (rlt) {
        return rlt;
      }
    }
  }

  /**
   * 获取菜单首条点击节点
   * @param {DocMenuNodeT} node 父节点
   * @returns {string} 返回节点id
   */
  getFirstHrefNode(node: DocMenuNodeT) {
    return node.children[0].children[0].id;
  }
}
